// 事件总线实现
// @/utils/eventBus.ts

type EventHandler = (...args: any[]) => void | Promise<void>

interface EventMap {
  [event: string]: EventHandler[]
}

interface EventOptions {
  once?: boolean
  priority?: number
}

interface HandlerWrapper {
  handler: EventHandler
  once: boolean
  priority: number
}

export class EventBus {
  private static instance: EventBus | null = null
  private events: Map<string, HandlerWrapper[]> = new Map()
  private maxListeners: number = 10
  private errorHandler?: (error: Error, event: string) => void

  private constructor() {}

  // 获取单例实例
  static getInstance(): EventBus {
    if (!EventBus.instance) {
      EventBus.instance = new EventBus()
    }
    return EventBus.instance
  }

  // 监听事件
  on(event: string, handler: EventHandler, options?: EventOptions): () => void {
    return this.addListener(event, handler, options)
  }

  // 监听一次
  once(event: string, handler: EventHandler): () => void {
    return this.addListener(event, handler, { once: true })
  }

  // 添加监听器
  private addListener(
    event: string,
    handler: EventHandler,
    options: EventOptions = {}
  ): () => void {
    const { once = false, priority = 0 } = options
    
    const wrapper: HandlerWrapper = {
      handler,
      once,
      priority
    }

    const handlers = this.events.get(event) || []
    
    // 检查监听器数量
    if (handlers.length >= this.maxListeners) {
      console.warn(
        `警告: 事件 "${event}" 的监听器数量已达到上限 (${this.maxListeners})`,
        '这可能是内存泄漏'
      )
    }

    // 按优先级插入
    const insertIndex = handlers.findIndex(h => h.priority < priority)
    if (insertIndex === -1) {
      handlers.push(wrapper)
    } else {
      handlers.splice(insertIndex, 0, wrapper)
    }

    this.events.set(event, handlers)

    // 返回取消监听函数
    return () => this.off(event, handler)
  }

  // 取消监听
  off(event: string, handler?: EventHandler): void {
    if (!handler) {
      // 移除该事件的所有监听器
      this.events.delete(event)
      return
    }

    const handlers = this.events.get(event)
    if (!handlers) return

    const filtered = handlers.filter(h => h.handler !== handler)
    
    if (filtered.length === 0) {
      this.events.delete(event)
    } else {
      this.events.set(event, filtered)
    }
  }

  // 触发事件
  emit(event: string, ...args: any[]): void {
    const handlers = this.events.get(event)
    if (!handlers || handlers.length === 0) return

    // 创建副本，防止在执行过程中修改
    const handlersCopy = [...handlers]
    
    // 过滤出需要移除的一次性监听器
    const handlersToKeep = handlers.filter(h => !h.once)
    this.events.set(event, handlersToKeep)

    // 异步执行所有处理器
    handlersCopy.forEach(wrapper => {
      this.executeHandler(wrapper.handler, event, args)
    })
  }

  // 同步触发事件
  emitSync(event: string, ...args: any[]): void {
    const handlers = this.events.get(event)
    if (!handlers || handlers.length === 0) return

    const handlersCopy = [...handlers]
    const handlersToKeep = handlers.filter(h => !h.once)
    this.events.set(event, handlersToKeep)

    // 同步执行所有处理器
    for (const wrapper of handlersCopy) {
      try {
        wrapper.handler(...args)
      } catch (error) {
        this.handleError(error as Error, event)
      }
    }
  }

  // 执行处理器
  private async executeHandler(
    handler: EventHandler,
    event: string,
    args: any[]
  ): Promise<void> {
    try {
      await handler(...args)
    } catch (error) {
      this.handleError(error as Error, event)
    }
  }

  // 处理错误
  private handleError(error: Error, event: string): void {
    if (this.errorHandler) {
      this.errorHandler(error, event)
    } else {
      console.error(`事件 "${event}" 处理出错:`, error)
    }
  }

  // 设置错误处理器
  setErrorHandler(handler: (error: Error, event: string) => void): void {
    this.errorHandler = handler
  }

  // 设置最大监听器数量
  setMaxListeners(max: number): void {
    this.maxListeners = max
  }

  // 获取事件的监听器数量
  listenerCount(event: string): number {
    const handlers = this.events.get(event)
    return handlers ? handlers.length : 0
  }

  // 获取所有事件名
  eventNames(): string[] {
    return Array.from(this.events.keys())
  }

  // 清理所有事件
  clear(): void {
    this.events.clear()
  }

  // 清理特定事件
  removeAllListeners(event?: string): void {
    if (event) {
      this.events.delete(event)
    } else {
      this.clear()
    }
  }

  // 等待事件
  waitFor(event: string, timeout?: number): Promise<any[]> {
    return new Promise((resolve, reject) => {
      let timeoutId: number | undefined

      const cleanup = () => {
        this.off(event, handler)
        if (timeoutId) {
          clearTimeout(timeoutId)
        }
      }

      const handler = (...args: any[]) => {
        cleanup()
        resolve(args)
      }

      this.once(event, handler)

      if (timeout) {
        timeoutId = setTimeout(() => {
          cleanup()
          reject(new Error(`等待事件 "${event}" 超时 (${timeout}ms)`))
        }, timeout) as unknown as number
      }
    })
  }

  // 创建命名空间
  namespace(prefix: string): NamespacedEventBus {
    return new NamespacedEventBus(this, prefix)
  }

  // 调试信息
  debug(): void {
    console.group('EventBus Debug Info')
    console.log('事件总数:', this.events.size)
    this.events.forEach((handlers, event) => {
      console.log(`事件 "${event}": ${handlers.length} 个监听器`)
    })
    console.groupEnd()
  }
}

// 命名空间事件总线
class NamespacedEventBus {
  constructor(
    private eventBus: EventBus,
    private prefix: string
  ) {}

  private prefixEvent(event: string): string {
    return `${this.prefix}:${event}`
  }

  on(event: string, handler: EventHandler, options?: EventOptions): () => void {
    return this.eventBus.on(this.prefixEvent(event), handler, options)
  }

  once(event: string, handler: EventHandler): () => void {
    return this.eventBus.once(this.prefixEvent(event), handler)
  }

  off(event: string, handler?: EventHandler): void {
    this.eventBus.off(this.prefixEvent(event), handler)
  }

  emit(event: string, ...args: any[]): void {
    this.eventBus.emit(this.prefixEvent(event), ...args)
  }

  emitSync(event: string, ...args: any[]): void {
    this.eventBus.emitSync(this.prefixEvent(event), ...args)
  }

  removeAllListeners(event?: string): void {
    if (event) {
      this.eventBus.removeAllListeners(this.prefixEvent(event))
    } else {
      // 移除该命名空间下的所有事件
      const allEvents = this.eventBus.eventNames()
      const prefixPattern = new RegExp(`^${this.prefix}:`)
      allEvents
        .filter(e => prefixPattern.test(e))
        .forEach(e => this.eventBus.removeAllListeners(e))
    }
  }

  waitFor(event: string, timeout?: number): Promise<any[]> {
    return this.eventBus.waitFor(this.prefixEvent(event), timeout)
  }
}

// 导出默认实例
export const eventBus = EventBus.getInstance()

// 使用示例：
// import { eventBus } from '@/utils/eventBus'
//
// // 监听事件
// const unsubscribe = eventBus.on('user:login', (data) => {
//   console.log('用户登录:', data)
// })
//
// // 监听一次
// eventBus.once('app:ready', () => {
//   console.log('应用就绪')
// })
//
// // 触发事件
// eventBus.emit('user:login', { userId: 1, name: 'John' })
//
// // 取消监听
// unsubscribe()
//
// // 使用命名空间
// const authEvents = eventBus.namespace('auth')
// authEvents.on('login', handler)
// authEvents.emit('login', data)

// 默认导出单例实例（兼容性）
export default eventBus 